#pragma once
#ifndef __THREAD_POLL_HPP__
#define __THREAD_POLL_HPP__

#include <iostream>
#include <pthread.h>
#include <string>
#include <vector>
#include <queue>
#include <functional>
#include "Thread.hpp"
#include "Cond.hpp"
#include "Lock.hpp"
#include "Log.hpp"


namespace ThreadPollModule
{
    using namespace ThreadModule;
    using namespace MutexModule;
    using namespace CondModule;
    using namespace LogModule;
    using task_t = std::function<void()>;
    
    const size_t defaultcap = 10;
    class ThreadPoll
    {
    private:
        //回调函数启动单个线程并在阻塞队列为空时阻塞
        void HandlerMethod()
        {
            while (true)
            {
                task_t task;
                {
                    //_mutex.Lock();
                    LockGuard guard(_mutex);
                    while (_task_queue.empty() && _is_running)
                    {
                        LOG(LogLevel::DEBUG) <<
                        ++_wait_num;
                        LOG(LogLevel::DEBUG) << "线程沉睡一次";
                        _cond.Wait(_mutex);
                        LOG(LogLevel::DEBUG) << "线程被唤醒一次";
                        --_wait_num;
                    }

                    if (_task_queue.empty() && !_is_running)
                    {
                        //_mutex.Unlock();
                        return;
                    }
                    

                    task = std::move(_task_queue.front());
                    _task_queue.pop();
                    //_mutex.Unlock();
                }                    // 这里自动解锁
                LOG(LogLevel::DEBUG) << "执行一次任务";
                task();              // 在锁外执行，防止死锁 & 异常风险
            }
        }

        ThreadPoll(size_t cap = defaultcap)
            : _cap(cap), _is_running(false), _wait_num(0)
        {
            for (size_t i = 0; i < _cap; ++i)
                _threads.emplace_back(std::bind(&ThreadPoll::HandlerMethod, this));
        }
        
    public:
        void Start()
        {
            LockGuard guard(_mutex);
            if(_is_running == true) return;
            _is_running = true;
            for(int i = 0; i < _cap; i++)
            {
                _threads[i].Start();
            }
        }


        void Stop()
        {
            LockGuard guard(_mutex);
            _is_running = false;
            _cond.Broadcast();
            LOG(LogLevel::DEBUG) << "进程池停止指令下达！";
        }

        bool Join()
        {
            // LockGuard guard(_mutex);
            if(_is_running == true)
            {
                LOG(LogLevel::DEBUG) << "进程池尚未停止运行，无法等待！";
                return false;
            }
            LOG(LogLevel::DEBUG) << "进程池开始等待！";
            LOG(LogLevel::DEBUG) << _wait_num << "个进程还在阻塞中！";
            if(_is_running == false)
            {
                for(int i = 0; i < _cap; i++)
                {
                    bool ret = _threads[i].Join();
                    if(ret)
                    {
                        LOG(LogLevel::DEBUG) << "线程:" << i << "等待成功";
                    }
                }
            }
            LOG(LogLevel::DEBUG) << "进程池等待成功，停止运行！";
            return true;
        }

        bool Enqueue(task_t in)
        {
            LockGuard guard(_mutex);
            if(_is_running)
            {
                _task_queue.push(in);
                if(_wait_num > 0)
                {
                    _cond.Signal();
                }
                return true;
            }
            else
            {
                return false;
            }
        }

        ~ThreadPoll()
        {
            LOG(LogLevel::DEBUG) << "线程池析构函数开始执行！";
            Stop();
            Join();
        }

        static ThreadPoll* GetInstance()
        {
            if(_inst == nullptr)
            {
                _inst_mutex.Lock();
                if(_inst == nullptr)
                {
                    _inst = new ThreadPoll(defaultcap);
                }
                _inst_mutex.Unlock();
            }
            return _inst;
        }

    private:
        size_t _cap; //线程池大小
        std::vector<Thread> _threads; //线程池

        std::queue<task_t> _task_queue; //任务阻塞队列
        bool _is_running; //线程池状态

        Mutex _mutex; //线程安全，保护共享资源
        Cond _cond; //线程在没有收到任务时在条件变量下等待
        size_t _wait_num; //阻塞等待的线程数量
    public:
        static ThreadPoll* _inst;  //单例模式
        static Mutex _inst_mutex;
    };
    ThreadPoll* ThreadPoll::_inst = nullptr;
    Mutex ThreadPoll::_inst_mutex;
}

#endif